﻿using Simple.Tools;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 Simple.SnowFlake
 * 接口名称 Woker
 * 开发人员：11920
 * 创建时间：2023/7/13 13:48:04
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace Simple.Tools.SnowFlake
{
	/// <summary>
	/// 
	/// </summary>
	public class Worker : IWorker
	{
		private static object OLOCK = new object();
		private static object WORKEROLOCK = new object();

		private static Worker WORKER;
		/// <summary>
		/// 
		/// </summary>
		public Worker()
		{
		}
		static Worker()
		{
			Defaultlength = 63;
			DefaultTimelength = 43;
			WorkLength = 10;
			SetMove();
			OffsetTime = new DateTime();
			IsOffset = false;
			SetWorkId(WorkId);
		}
		/// <summary>
		/// 设置工作服务id
		/// </summary>
		/// <param name="workerId">工作机器id</param>
		/// <param name="length">工作机器所占用位长度</param>
		/// <exception cref="ArgumentException"></exception>
		/// <exception cref="InvalidOperationException"></exception>
		public static void SetWorkId(int workerId, int length = 10)
		{
			if (workerId >= Math.Pow(2, WorkLength))
			{
				throw new ArgumentException();
			}

			if (length >= Defaultlength - DefaultTimelength)
			{
				throw new InvalidOperationException();
			}
			WorkId = workerId;
			if (WorkLength != length)
			{
				WorkLength = length;
				SetMove();
			}
			Max = (int)Math.Pow(2, Defaultlength - DefaultTimelength - WorkLength);
		}
		/// <summary>
		/// 
		/// </summary>
		private static void SetMove()
		{
			LeftMoveTimeLength = Defaultlength - DefaultTimelength;
			LeftMoveWorkLength = LeftMoveTimeLength - WorkLength;
			DateTimeExtension.SetYearLength(11);
		}

		/// <summary>
		/// 设置时间偏移量 
		/// 当前获取时间减去 传入的偏移值
		/// </summary>
		/// <param name="time"></param>
		public static void SetOffset(DateTime time)
		{
			OffsetTime = time;
			IsOffset = true;
		}
		/// <summary>
		/// 自增计数
		/// </summary>
		private static int count;

		private static int Defaultlength;
		/// <summary>
		/// 时间长度
		/// </summary>
		private static int DefaultTimelength;
		/// <summary>
		/// 工作长度
		/// </summary>
		private static int WorkLength;
		private static int Max;


		private static int LeftMoveWorkLength;
		private static int LeftMoveTimeLength;

		private static int WorkId;


		private static DateTime OffsetTime;
		private static bool IsOffset;
		/// <summary>
		/// 时间戳
		/// </summary>
		private static long LastTimeTickes;

		private static readonly object COUNTLOCK = new object();
		/// <summary>
		/// 异步获取ID
		/// </summary>
		/// <returns></returns>
		public async Task<long> NextIdAsync()
		{
			return await Task.Run(() =>
			{
				return NextId();
			});

		}
		/// <summary>
		/// 获取一个可用ID
		/// </summary>
		/// <returns></returns>
		public long NextId()
		{
			return GetId();
		}
		/// <summary>
		/// 获取id
		/// </summary>
		/// <returns></returns>
		public static long GetId()
		{
			lock (COUNTLOCK)
			{
				long Id = 0;

				long timeTickes = 0;
				DateTime time = DateTime.Now;

				if (IsOffset)
				{
					timeTickes = time.GetTimeTicks(OffsetTime);
				}
				else
				{
					timeTickes = time.GetTimeTicks();
				}
				if (count == Max || LastTimeTickes!= timeTickes)
				{
					LastTimeTickes = timeTickes;
					count = 0;
				}
				else
				{
					count++;
				}
                Id = (timeTickes << LeftMoveTimeLength | (long)WorkId << LeftMoveWorkLength | (long)count);
				return Id;
			}

		}

		/// <summary>
		/// 获取id
		/// </summary>
		/// <returns></returns>
		public static long GetId(DateTime time)
		{
			lock (COUNTLOCK)
			{
				long Id = 0;

				long timeTickes = 0;

				if (IsOffset)
				{
					timeTickes = time.GetTimeTicks(OffsetTime);
				}
				else
				{
					timeTickes = time.GetTimeTicks();
				}
				if (count == Max || LastTimeTickes != timeTickes)
				{
					LastTimeTickes = timeTickes;
					count = 0;
				}
				else
				{
					count++;
				}
				Id = (timeTickes << LeftMoveTimeLength | (long)WorkId << LeftMoveWorkLength | (long)count);
				return Id;
			}

		}
		/// <summary>
		/// 创建一个worker
		/// </summary>
		/// <returns></returns>
		public static IWorker Builder()
		{
			if (SimpleCheck.IsNull(WORKER))
			{
				lock (WORKEROLOCK)
				{
					if (SimpleCheck.IsNull(WORKER))
					{
						WORKER = new Worker();
					}
				}
			}
			return WORKER;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		private static int GetCount()
		{
			int temp = 0;
			lock (COUNTLOCK)
			{
				if (count == Max)
				{
					count = 0;
				}
				else
				{
					count++;
					temp = count;
				}
			}
			return temp;
		}
	}
}
